package compilers.types;

import java.io.BufferedWriter;
import java.io.IOException;

import compilers.condition.Factor;
import compilers.node.Identifier;
import compilers.table.MemScope;

public abstract class Type extends Factor {
	public abstract boolean isNumeric();	
	public abstract void print(int tab);
	public abstract void generate(BufferedWriter writer, MemScope scope) throws IOException;
	public Type getBiggestType() { return this; }
	
	public abstract Type computeOperation(Type second, String op);
	public abstract Type computeFactor(String pre);
	public float getfValue() {
		return fValue;
	}
	public void setfValue(float fValue) {
		this.fValue = fValue;
	}
	public abstract Type newInit();
	
	public abstract char getPType();

	boolean isConstant;
	boolean isArray;
	Identifier fIdentifier;
	int fArraySize;
	int fIndex;
	float fValue;
	boolean fValueSet; // used for optimization
	
	Type(boolean constant, float value) {
		fArraySize = 0;
		fIndex = 0;
		isConstant = constant;
		isArray = false;
		fValue = value;
	}
	
	public Type clone() {
		Type t;
		if (this instanceof CharType) {
			t = new CharType(fValue, isConstant);
		} else if (this instanceof IntType) {
			t = new IntType(fValue, isConstant);
		} else {
			t = new FloatType(fValue, isConstant);
		}
		
		t.fIdentifier = fIdentifier;
		t.isArray = isArray;
		t.fArraySize = fArraySize;
		t.fIndex = fIndex;
		t.fValueSet = fValueSet;
		
		return t;
		
	}
	
	public boolean isfValueSet() {
		return fValueSet;
	}
	public void setfValueSet(boolean fValueSet) {
		this.fValueSet = fValueSet;
	}
	public void setIdentifier(Identifier fIdentifier) {
		this.setfIdentifier(fIdentifier);
	}
	
	public void setArray() {
		isArray = true;
	}
	
	public boolean isArray() {
		return isArray;
	}
	
	public boolean isConstant() {
		return isConstant;
	}
	
	public void setIndex(int i) {
		fIndex = i;
	}
	
	public int getIndex() {
		return fIndex;
	}

	public int getArray() {
		return fArraySize;
	}

	public void setArray(int array) {
		this.isArray = array > 0;
		this.fArraySize = array;
	}
	
	public Identifier getfIdentifier() {
		return fIdentifier;
	}
	
	public void setfIdentifier(Identifier fIdentifier) {
		this.fIdentifier = fIdentifier;
	}
	
	public String str(int address, MemScope scope) {
		return "str " + this.getPType() + " " + scope.getDepth(getfIdentifier().getfIdentifier(), 0) + " " + address + "\n";	
	}

}
